package com.affectu.search.fetch.thread;

import java.util.Date;
import java.util.concurrent.Callable;

import org.hibernate.Session;
import org.hibernate.search.FullTextSession;
import org.htmlparser.Parser;
import org.htmlparser.filters.NodeClassFilter;
import org.htmlparser.tags.LinkTag;
import org.htmlparser.util.NodeList;

import com.affectu.common.base.UtilBase;
import com.affectu.common.util.PersistanceUtil;
import com.affectu.task.OuterTask;

/**
 * Oct 12, 2008
 * 
 * @author daniel nathan
 */
public abstract class OutTaskThread extends UtilBase implements
		Callable<Boolean>, IFetchBase<OuterTask> {

	private static int BUDGET_LIMIT = 300;// 300以下就不用抓了

	private String url;

	private String subpagePattern;

	public OutTaskThread(String url, String subpagePattern) {
		this.url = url;
		this.subpagePattern = subpagePattern;
	}

	public Boolean call() {
		Boolean flag = new Boolean(false);
		try {
			this.spidePage();
			flag = Boolean.valueOf(true);
		} catch (Exception ex) {
			this.logAffectuException(ex, "出错:" + url);
		}
		return flag;
	}

	public void spidePage() {
		this.log("Fetch task begin..." + url);

		try {
			Parser p = new Parser(url);
			p.setEncoding("UTF-8");
			NodeList linkList = p.parse(new NodeClassFilter(LinkTag.class)); // 使用NodeClassFilter

			for (int i = 0; i < linkList.size(); i++) {// one level directory
				String subURL = ((LinkTag) linkList.elementAt(i)).getLink()
						.toString();
				if (subURL.indexOf(subpagePattern) != -1) {

					if (!this.checkLink(subURL)) {
						this.saveObject(this.spideSubPage(subURL));
					} else {
						this.log("already haved- url:" + subURL);// break;
					}
				}
			}

		} catch (Exception ex) {
			this.logAffectuException(ex, "取任务异常:" + url);
		}

		this.log("Fetch task end..." + url);
	}

	public abstract OuterTask spideSubPage(String url);

	public boolean saveObject(OuterTask outTask) {
		lock.lock();
		boolean flag = false;
		FullTextSession em = PersistanceUtil.getInstance().getFullTextSession();
		try {
			if (outTask.getBudget() >= BUDGET_LIMIT) {
				outTask.setCreateDate(new Date());
				em.save(outTask);
			} else {
				this.log("当前金额为" + outTask.getBudget() + ":[" + BUDGET_LIMIT
						+ "以下，暂不予入库.]");
			}
			flag = true;
		} catch (Exception ex) {
			this.logAffectuException(ex, "存任务异常");
		} finally {
			em.close();
		}
		lock.unlock();
		return flag;
	}

	public boolean checkLink(String link) {
		boolean flag = false;
		Session em = PersistanceUtil.getInstance().getSession();
		try {

			Object ov = em.createSQLQuery(
					"select count(n.id) from OuterTask n where n.url=:link")
					.setParameter("link", link).uniqueResult();
			if (Integer.valueOf(ov.toString()).intValue() > 0) {
				flag = true;
			}
		} catch (Exception ex) {
			this.logAffectuException(ex, "检查link出错:" + link);
		} finally {
			em.close();
		}
		return flag;
	}
}
